#ifndef __PROCESS_POOL_HPP__
#define __PROCESS_POOL_HPP__
#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <functional>
#include "Task.hpp"
#include "channel.hpp"
// typedef std::function<void()> work_t;
using work_t = std::function<void()>;

enum
{
    OK = 0,
    //有第一个数据0其他后面的就依次赋值
    UsageError,
    PipeError,
    ForkError
};

class ProcessPool
{
public:
    ProcessPool(int n, work_t w)
        : work(w)
        , processnum(n)
    {}
    // channels : 输出型参数
    // work_t work: 回调

    int InitProcessPool() {
      //创建指定个数的进程
      for (int i = 0; i < processnum; i++) {
        //先有管道
        int pipefds[2] = {0};
        int n = pipe(pipefds);
        if (n < 0) {
          return PipeError;
        }

        //创建进程
        pid_t id = fork();
        if (id < 0) {
          return ForkError;
        }

        //建立通信管道
        if (id == 0) {
          // 关闭历史wfd
          std::cout << getpid() << ", child close history fd: ";
          for (auto &c : channels) {
            std::cout << c.Wfd() << " ";
            c.close();
          }
          std::cout << " over" << std::endl;
          ::close(pipefds[1]); // read
          // child
          std::cout << "debug: " << pipefds[0] << std::endl;
          dup2(pipefds[0], 0);
          work();
          ::exit(0);
        }
        // ⽗进程执⾏
        ::close(pipefds[0]); // write
        channels.emplace_back(pipefds[1], id);
        // Channel ch(pipefd[1], id);
        // channels.push_back(ch);
      }
      return OK;
    }

    void DispatchTask()
    {
        int who = 0;
        //派发任务
        int num = 20;
        while(num--)
        {
            //选择一个任务 整数
            int task = tm.SelectTask();
            //选择一个子进程
            Channel& curr = channels[who++];
            who %= channels.size();
            std::cout << "######################" << std::endl;
            std::cout << "send " << task << " to " << curr.name() << ", 任务还剩: " << num << std::endl;
            std::cout << "######################" << std::endl;

            //派发任务
            curr.send(task);

            sleep(1);
        }
    }

    void CleanProcessPool()
    {
        for (auto &c : channels)
        {
            c.close();
            pid_t rid = ::waitpid(c.Id(), nullptr, 0);
            if (rid > 0)
            {
                std::cout << "child " << rid << " wait ... success" <<
                std::endl;
            }
        }
    }
    void DebugPrint()
    {
    for (auto &c : channels)
    {
        std::cout << c.name() << std::endl;
    }
    }

private:
    std::vector<Channel> channels;
    int processnum;
    work_t work;
};

#endif